﻿using SuperMap.Data;
using SuperMap.Realspace;
using SuperMap.Realspace.NetworkAnalyst;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Ycjw.PipeLine.Map.Basic.Conditions;

namespace Ycjw.PipeLine.Map.Tools.Conditions
{
    public class ConnectedAnalystToolBar : BasicToolBar
    {
        private bool LineSelected = false;
        private GeoPoint3D m_GeoPoint3D01;
        private GeoPoint3D m_GeoPoint3D02;

        private readonly string m_GeoPoint3D01Tag ="FirstPoint";
        private readonly string m_GeoPoint3D02Tag ="SecondPoint";

        private readonly List<string> m_IndexOfLineResult = new List<string>();

        private ToolStripButton m_BtnSetFirstPoint;
        private ToolStripButton m_BtnSetSecondPoint;

        private TransportationAnalyst3D m_TransportationAnalyst;
        private ToolStripComboBox m_ToolStripComboBoxLayer;
        public ConnectedAnalystToolBar() : base()
        {
        }

        private void ToolStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if(sender == this.m_BtnSetFirstPoint || sender == this.m_BtnSetSecondPoint)
            {
                return;
            }
            m_BtnSetSecondPoint.Checked = false;
            m_BtnSetFirstPoint.Checked = false;
        }
        private void ClearPoint(int flag = 0)
        {
            if (flag <= 0)
            {
                var index = Scene.TrackingLayer.IndexOf(m_GeoPoint3D01Tag);
                if (index > -1) Scene.TrackingLayer.Remove(index);
            }
            if (flag >= 0)
            {
                var index = Scene.TrackingLayer.IndexOf(m_GeoPoint3D02Tag);
                if (index > -1) Scene.TrackingLayer.Remove(index);
            }
        }
        /// <summary>
        /// flag=0 删除全部
        /// flag=-1删除第一个点的text
        /// flag=1 删除第二个点的text
        /// </summary>
        /// <param name="flag"></param>
        private void ClearText(int flag = 0)
        {
            if (flag <= 0)
            {
                var index = Scene.TrackingLayer.IndexOf("分析点-点一");
                if (index > -1) Scene.TrackingLayer.Remove(index);
            }
            if (flag >= 0)
            {
                var index = Scene.TrackingLayer.IndexOf("分析点-点二");
                if (index > -1) Scene.TrackingLayer.Remove(index);
            }
        }
        private void BtnClear_Click(object sender, EventArgs e)
        {
            ClearLine();
            ClearPoint();
            ClearText();
        }

        private void BtnAnalyst_Click(object sender, EventArgs e)
        {
            Analyst();
        }

        private void ClearLine()
        {
            for(int i = 0;i < m_IndexOfLineResult.Count; i++)
            {
                var index = Scene.TrackingLayer.IndexOf(m_IndexOfLineResult[i]);
                if(index > -1) Scene.TrackingLayer.Remove(index);
            }
            m_IndexOfLineResult.Clear();
        }
        private void Analyst()
        {
            ClearLine();
            SetAnalystSetting();
            TransportationAnalystParameter3D parameter = new TransportationAnalystParameter3D
            {
                WeightName = "length",

                // 设置最佳路径分析的返回对象
                // Set the return object of the optimal path analysis
                Points = new Point3Ds(new Point3D[] { m_GeoPoint3D01.Position, m_GeoPoint3D02.Position }),
                //parameter.IsNodesReturn = true;
                //parameter.IsEdgesReturn = true;
                //parameter.IsPathGuidesReturn = true;
                IsRoutesReturn = true
            };

            // 进行分析并显示结果
            // Analyze
            var result = m_TransportationAnalyst.FindPath(parameter);
            if(result == null)
            {
                Sunny.UI.UIMessageTip.ShowWarning("选择的两点不连通");
                return;
            }
            var routes = result.Routes;

            for (int i = 0; i < routes.Length; i++)
            {
                var r = routes[i];
                r.Style3D = new GeoStyle3D()
                {
                    LineColor = Color.Gold,
                    LineWidth = 12,
                    AltitudeMode = AltitudeMode.Absolute,
                    BottomAltitude = 0.1
                };
                var tag = "Routes_" + i;
                Scene.TrackingLayer.Add(r, tag);
                m_IndexOfLineResult.Add(tag);
            }
        }
        private void SetAnalystSetting()
        {
            if (m_TransportationAnalyst == null)
                m_TransportationAnalyst = new TransportationAnalyst3D();
            TransportationAnalystSetting3D setting = new TransportationAnalystSetting3D
            {
                NetworkDataset = SelectedLayerDataset()
            };
            if (setting.NetworkDataset == null)
            {
                Sunny.UI.UIMessageTip.ShowWarning("请先选择网络一个数据");
                return;
            }

            setting.EdgeIDField = "SmID";
            setting.NodeIDField = "SSNODEID";
            setting.EdgeNameField = "SmID";
            setting.Tolerance = 100;

            WeightFieldInfos3D weightFieldInfos = new WeightFieldInfos3D();
            WeightFieldInfo3D weightFieldInfo = new WeightFieldInfo3D
            {
                FTWeightField = "smLength",
                TFWeightField = "smLength",
                Name = "length"
            };
            weightFieldInfos.Add(weightFieldInfo);
            setting.WeightFieldInfos = weightFieldInfos;
            setting.FNodeIDField = "SSFNODE";
            setting.TNodeIDField = "SSTNODE";

            m_TransportationAnalyst.AnalystSetting = setting;
            m_TransportationAnalyst.Load();
        }

        private DatasetVector SelectedLayerDataset()
        {
            if (m_ToolStripComboBoxLayer.SelectedItem == null) return null;
            var layer = m_ToolStripComboBoxLayer.SelectedItem as LayerAttr;
            return layer.DatasetVector;
        }
        private void BtnSetPoint_Click(object sender, EventArgs e)
        {
            ClearLine();
            if (!m_BtnSetFirstPoint.Checked && !m_BtnSetSecondPoint.Checked)
            {
                SceneControl.MouseUp -= new System.Windows.Forms.MouseEventHandler(SceneControl_MouseUp);
                SceneControl.Cursor = Cursors.Default;
                return;
            }

            if (sender == m_BtnSetFirstPoint)
            {
                m_BtnSetSecondPoint.Checked = false;
            }
            else if (sender == m_BtnSetSecondPoint)
            {
                m_BtnSetFirstPoint.Checked = false;
            }

            SceneControl.Action = SuperMap.UI.Action3D.Select;
            SceneControl.MouseUp -= new MouseEventHandler(SceneControl_MouseUp);
            SceneControl.MouseUp += new MouseEventHandler(SceneControl_MouseUp);
        }
        public override void AfterClose()
        {
            Scene.TrackingLayer.Clear();
            SceneControl.MouseUp -= new MouseEventHandler(SceneControl_MouseUp);
            SceneControl.Cursor = Cursors.Default;
            this.SceneControl.ObjectSelectChanged -= SceneControl_ObjectSelectChanged;
            base.AfterClose();
        }
        void SceneControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (!m_BtnSetFirstPoint.Checked && !m_BtnSetSecondPoint.Checked) return;
            try
            {

                // 左键抬起且鼠标状态为绘制状态时
                // The left key picks and the mouse state is drawn
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    Task.Factory.StartNew(() => {
                        Thread.Sleep(200);
                    }).ContinueWith((t) => {
                        if (!this.LineSelected) return;
                        Point3D point3D = new Point3D();
                        point3D = SceneControl.Scene.PixelToGlobe(new Point(e.X, e.Y), PixelToGlobeMode.TerrainAndModel);
                        GeoPoint3D geoPoint3D = new GeoPoint3D(point3D);
                        CreatePoint(geoPoint3D);

                    }, TaskScheduler.FromCurrentSynchronizationContext());
                }
            }
            catch (System.Exception ex)
            {
                Commons.LogHelper.Error(ex.Message);
            }
        }
        private void SetPointStyle(GeoPoint3D point)
        {
            point.Style3D = new GeoStyle3D()
            {
                AltitudeMode = AltitudeMode.Absolute,
                MarkerColor = Color.Yellow,
                MarkerSize = 16
            };
        }
        private void AddPointText(GeoPoint3D point, string text)
        {
            GeoText3D geoText = new GeoText3D(new TextPart3D(text, point.Position));
            Basic.SuperMap.Styles.SetResultTextStyle(geoText);
            Scene.TrackingLayer.Add(geoText, "分析点-" + text) ;
        }
        private void CreatePoint(GeoPoint3D point)
        {
            SetPointStyle(point);
            if (m_BtnSetFirstPoint.Checked)
            {
                if (m_GeoPoint3D01 != null)
                {
                    ClearPoint(-1);
                    ClearText(-1);
                }
                m_GeoPoint3D01 = point;
                Scene.TrackingLayer.Add(m_GeoPoint3D01, m_GeoPoint3D01Tag);
                AddPointText(point, "点一");
            }
            else if (m_BtnSetSecondPoint.Checked)
            {
                if (m_GeoPoint3D02 != null)
                {
                    ClearPoint(1);
                    ClearText(1);
                }
                m_GeoPoint3D02 = point;
                Scene.TrackingLayer.Add(m_GeoPoint3D02, m_GeoPoint3D02Tag);
                AddPointText(point, "点二");
            }
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            m_ToolStripComboBoxLayer = CreateLayerSelection();

            base.ToolStrip.Items.Add(new ToolStripSeparator());

            m_BtnSetFirstPoint = CreateButton("设置第一个点", "btnSetFirstPoint");
            m_BtnSetFirstPoint.CheckOnClick = true;
            m_BtnSetSecondPoint = CreateButton("设置第二个点", "btnSetSecondPoint");
            m_BtnSetSecondPoint.CheckOnClick = true;

            ToolStripButton btnAnalyst = CreateButton("分析", "btnAnalyst");
            ToolStripButton btnClear = CreateButton("清除", "btnClear");

            m_BtnSetFirstPoint.Click += BtnSetPoint_Click;
            m_BtnSetSecondPoint.Click += BtnSetPoint_Click;

            btnAnalyst.Click += BtnAnalyst_Click;

            btnClear.Click += BtnClear_Click;

            base.ToolStrip.ItemClicked += ToolStrip_ItemClicked;

            this.SceneControl.ObjectSelectChanged += SceneControl_ObjectSelectChanged;
        }

        private void SceneControl_ObjectSelectChanged(object sender, SuperMap.UI.ObjectSelectChangedEventArgs e)
        {
            LineSelected = false;
            if (e.Count <= 0)
            {
                return;
            }
            Selection3D[] selection3d = SceneControl.Scene.FindSelection(true);
            if (selection3d.Length == 0) return;
            var sel = selection3d[0];
            if (!sel.Layer.Caption.EndsWith("管线")) return;
            LineSelected = true;
        }

        private ToolStripComboBox CreateLayerSelection()
        {
            ToolStripLabel label = new ToolStripLabel("LayersCBLabel")
            {
                Text = "选择图层："
            };
            ToolStripComboBox cb = new ToolStripComboBox
            {
                DropDownStyle = ComboBoxStyle.DropDownList
            };
            cb.ComboBox.DisplayMember = "Text";
            cb.ComboBox.ValueMember = "Name";

            var dataSource = new List<LayerAttr>();
            for (int i = 0; i < Scene.Layers.Count; i++)
            {
                var lyr = Scene.Layers[i];
                if (lyr.Type != Layer3DType.Dataset) continue;
                var lyrDataset = lyr as Layer3DDataset;
                if (lyrDataset.Dataset.Type != DatasetType.Network3D) continue;
                var dataset = lyrDataset.Dataset as DatasetVector;
                var layerAttr = new LayerAttr
                {
                    Name = lyr.Name,
                    Text = lyr.Caption,
                    DatasetVector = dataset
                };
                dataSource.Add(layerAttr);
            }
            if(dataSource.Count == 0)
            {
                for (int i = 0; i < Scene.Layers.Count; i++)
                {
                    var lyr = Scene.Layers[i];
                    if(!lyr.Caption.EndsWith("管线")) continue;
                    var name = lyr.Name;
                    var tmp = name.Split('@');
                    if (tmp.Length != 2) continue;
                    var dtSource = Scene.Workspace.Datasources[tmp[1]];
                    var dtSet = dtSource.Datasets[tmp[0]];

                    if (dtSet.Type != DatasetType.Network3D) continue;
                    var dataset = dtSet as DatasetVector;
                    var layerAttr = new LayerAttr
                    {
                        Name = lyr.Name,
                        Text = lyr.Caption,
                        DatasetVector = dataset
                    };
                    dataSource.Add(layerAttr);
                }
            }
            cb.ComboBox.DataSource = dataSource;

            base.ToolStrip.Items.Add(new ToolStripSeparator());
            base.ToolStrip.Items.Add(label);
            base.ToolStrip.Items.Add(cb);
            return cb;
        }
        private ToolStripButton CreateButton(string text, string name)
        {
            var button = new ToolStripButton()
            {
                DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,
                Text = text,
                Name = name
            };
            base.ToolStrip.Items.Add(button);
            return button;
        }

        public class LayerAttr
        {
            private string name;
            private string text;
            private DatasetVector datasetVector;

            public DatasetVector DatasetVector { get => datasetVector; set => datasetVector = value; }
            public string Name { get => name; set => name = value; }
            public string Text { get => text; set => text = value; }
        }

    }

}
